//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#pragma once

#include "Graphics/Resources/Texture.h"
#include "Graphics/Systems/BatchRender.h"
#include "Graphics/MetaData/Meta.ForwardDecl.h"
#include "Graphics/Primitives/RectPrimitives.h"

namespace Engine
{
namespace Graphics
{

	class Sprite2D;
	SHARED_POINTER( Sprite2D );



	//
	// Sprite 2D
	//

	class Sprite2D : public Resource
	{
		friend struct SpriteLoader;
		friend struct ::MetaData::Sprite2dCfg;

	// types
	public:
		//
		// Sprite Load Parameters
		//
		struct SpriteLoadParams : ResLoadParams
		{
		// variables
		public:

		// methods
		public:
			SpriteLoadParams () : ResLoadParams( Signature() )
			{}

			static signature_t Signature ()
			{
				return CompileTime::TSignature8< 'G', 'S', 'P', 'R', '2', 'D' >::value;
			}
		};


		struct Physics
		{
			vec2		scale;
			vec2		center;
			int			shape;
			float		friction;
			float		mass;
			///
			Physics () : shape(0), friction(0.0f), mass(0.0f) {}
		};


		struct Animation
		{
			uvec2		frameInterval;
			//uvec2		type;			// begin, end
			float		rate;
			bool		blend;			// blend 2 near frames
			///
			Animation () : rate(0.0f), blend(false) {}

			uint FramesCount ()	const	{ return frameInterval[1] - frameInterval[0] + 1; }
		};


		struct Instance
		{
			friend class Sprite2D;

		// variables
		private:
			uvec2		_animType;		// begin, end
			usize		_animIndex;
			float		_frameTime;
			uint		_prevFrame;
			uint		_nextFrame;
			float		_frameInterpolation;
			bool		_looping;
		
		// methods
		public:
			Instance () :
				_animIndex(0), _frameTime(0.0f), _prevFrame(0),
				_nextFrame(0), _frameInterpolation(0.0f)
			{}

			virtual ~Instance () {}

			virtual void OnAnimationEnd (const Sprite2DPtr &) {}

			void SetLooping (bool looping)	{ _looping = looping; }
		};


		typedef map< uvec2, Animation >		anim_map_t;
		typedef array< rect >				texc_array_t;


	// variables
	protected:
		Texture			_texture;
		BatchMaterial	_material;

		anim_map_t		_animations;
		texc_array_t	_texcoords;
		uint32_array_t	_frames;

		color4u			_color;


	// methods
	public:
		Sprite2D (const EngineSubSystemsRef ess);
		~Sprite2D ();


		void Draw (const rect &region, const Instance &inst) const;
		void Update (Instance &inst, float timeDelta) const;

		bool SetAnimation (Instance &inst, uint animType, float time = 0.0f) const;
		bool ChangeAnimation (Instance &inst, uint animType) const;

		bool HasAnimation (uint animType) const;
		bool HasAnimation (uint animBegin, uint animEnd) const;


		// Resource //
		virtual bool SwapData (const ResourcePtr &) override;
		
		virtual bool IsLoadedWithParams (const ResLoadParams &params) const override;
		
		virtual bool IsValid () const override;


		static Sprite2DPtr	New (const EngineSubSystemsRef ess);

		static SpriteLoadParams	GetDefaultLoadParams ();
	};


}	// Graphics
}	// Engine